package org.xxpay.pay.channel.ywxpay;

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.domain.api.AbstractRes;
import org.xxpay.core.common.domain.api.ApiBuilder;
import org.xxpay.core.common.domain.api.PayRes;
import org.xxpay.core.common.domain.api.msg.QueryRetMsg;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.util.XXPayUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.core.entity.WxUser;
import org.xxpay.pay.channel.BasePayment;
import org.xxpay.pay.mq.BaseNotify4MchPay;

import java.net.URLEncoder;

/**
 * @author: dingzhiwei
 * @date: 19/1/22
 * @description: 云微信支付接口
 */
@Service
public class YwxpayPaymentService extends BasePayment {

    @Autowired
    public BaseNotify4MchPay baseNotify4MchPay;

    @Autowired
    public YwxpayService ywxpayService;

    private static final MyLog _log = MyLog.getLog(YwxpayPaymentService.class);

    @Override
    public String getChannelName() {
        return YwxpayConfig.CHANNEL_NAME;
    }

    /**
     * 支付
     * @param payOrder
     * @return
     */
    @Override
    public AbstractRes pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        AbstractRes retObj;
        switch (channelId) {
            case YwxpayConfig.CHANNEL_NAME_QR :
                retObj = doPayQrReq(payOrder);
                break;

            default: return ApiBuilder.bizError("不支持的渠道[channelId="+channelId+"]");
        }
        return retObj;
    }

    /**
     * 查询订单
     * @param payOrder
     * @return
     */
    @Override
    public QueryRetMsg query(PayOrder payOrder) {
        return QueryRetMsg.waiting();
    }

    /**
     * 微信扫码支付
     * @param payOrder
     * @return
     */
    public AbstractRes doPayQrReq(PayOrder payOrder) {
        YwxpayConfig ywxpayConfig = new YwxpayConfig(getPayParam(payOrder));
        PayRes retObj = ApiBuilder.buildSuccess(PayRes.class);
        JSONObject paramMap = new JSONObject();
        String url = ywxpayConfig.getReqUrl();
        try {
            String reqData = XXPayUtil.genUrlParams(paramMap);
            _log.info("{}请求数据:{}", getChannelName(), reqData);
            WxUser wxUser = getAvailableWxUser(ywxpayConfig);
            if(wxUser == null) {
                _log.info("{}没有可用的微信收款用户,serverId={}", getChannelName(), ywxpayConfig.getServerId());
                return ApiBuilder.bizError("没有可以收款的微信用户!");
            }
            JSONObject resObj = ywxpayService.getPaymentQrcode(url, wxUser, payOrder);
            _log.info("{}返回数据:{}", getChannelName(), resObj);
            if(resObj == null) {
                return ApiBuilder.bizError("上游通道返回空!");
            }

            if("0".equals(resObj.getString("code"))) {
                JSONObject data = resObj.getJSONObject("data");
                String payUrl = data.getString("payUrl");   // 微信二维码地址

                JSONObject attachObj = new JSONObject();
                attachObj.put("randomId", wxUser.getRandomId());
                attachObj.put("userId", wxUser.getUserId());
                String channelAttach = attachObj.toJSONString();
                int updateCount = commonService.payOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null, channelAttach);
                _log.info("[{}]更新订单状态为支付中:payOrderId={},result={}", getChannelName(), payOrder.getPayOrderId(), updateCount);
                retObj.setQrInfo(payUrl, genCodeImgUrl(URLEncoder.encode(payUrl)));
                return retObj;
            }else {
                return ApiBuilder.bizError("操作失败!");
            }
        } catch (Exception e) {
            _log.error(e, "");
            return ApiBuilder.bizError("操作失败!");
        }
    }

    private WxUser getAvailableWxUser(YwxpayConfig ywxpayConfig) {
        String serverId = ywxpayConfig.getServerId();
        Long dayMaxAmount = ywxpayConfig.getDayMaxAmount();
        Long dayMaxNumber = ywxpayConfig.getDayMaxNumber();
        WxUser wxUser = commonService.wxUserService.findByAvailable(serverId, dayMaxAmount, dayMaxNumber);
        return wxUser;

    }

}
